/* KeyHandler.cpp
Copyright (c) 2008 Michael Zahniser
Please note the license terms (MIT license) at the end of this document.

Function definitions for the KeyHandler class.
*/

#ifndef __SDL_KEY_HANDLER_CPP__
#define __SDL_KEY_HANDLER_CPP__

#include "KeyHandler.h"



template <class Client>
KeyHandler<Client>::KeyHandler()
	: client(NULL)
{
}



// SetClient:
// Set the object whose functions will respond to the key events.
// KeyHandler<Client> should be a friend of Client in order for the
// handler functions to be private in Client.
template <class Client>
void KeyHandler<Client>::SetClient(Client *client)
{
	this->client = client;
}



// SetHandler:
// Set the handler for the given key and set of modifiers.
template <class Client>
void KeyHandler<Client>::SetHandler(SDLKey key, int mod, MemFun fun)
{
	(*this)(key, mod) = fun;
}



// SetHandler:
// Set the handler for the given key and set of modifiers.
template <class Client>
void KeyHandler<Client>::SetHandler(char key, int mod, MemFun fun)
{
	(*this)(key, mod) = fun;
}



// operator():
// Alternate syntax for setting a handler.
template <class Client>
typename KeyHandler<Client>::MemFun &KeyHandler<Client>::operator()(SDLKey key, int mod)
{
	return handler[Encode(key, static_cast<SDLMod>(mod))];
}



// operator():
// Alternate syntax for setting a handler.
template <class Client>
typename KeyHandler<Client>::MemFun &KeyHandler<Client>::operator()(char key, int mod)
{
	return (*this)(static_cast<SDLKey>(key), mod);
}



// Handle:
// Handle the given key press.
// Returns true if the key was handled. The key will always be handled
// unless there is no default handler that supports all the key's modifiers.
template <class Client>
bool KeyHandler<Client>::Handle(SDLKey key, SDLMod mod)
{
	if(!client)
		return false;

	// Search for handlers in this order:
	else if(HandleCode(key, mod, Encode(key, mod)))
		return true;
	else if(HandleCode(key, mod, Encode(key, ANY_MOD)))
		return true;
	else if(HandleCode(key, mod, Encode(SDLK_UNKNOWN, mod)))
		return true;
	else if(HandleCode(key, mod, Encode(SDLK_UNKNOWN, ANY_MOD)))
		return true;

	return false;
}



// HandleExact:
// Handle the exact key code given. Return true if handled.
template <class Client>
bool KeyHandler<Client>::HandleCode(SDLKey key, SDLMod mod, Uint32 encoded)
{
	HandlerIt it = handler.find(encoded);
	if(it == handler.end())
		return false;

	((*client).*(it->second))(key, mod);
	return true;
}



// Encode:
// Convert the given key and modifier into the format used by the handler map.
template <class Client>
Uint32 KeyHandler<Client>::Encode(SDLKey key, SDLMod mod)
{
	return (key << 4) |
		(((mod & KMOD_SHIFT) != 0) << 0) |
		(((mod & KMOD_ALT) != 0) << 1) |
		(((mod & (KMOD_CTRL | KMOD_META)) != 0) << 2) |
		((mod == ANY_MOD) << 3);
}



#endif

/* Copyright (c) 2008 Michael Zahniser

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. */
